package com.equipment_management_p1.service.Impl;
import com.equipment_management_p1.service.IEquipmentService;
import com.equipment_management_p1.service.ex.ServiceException;
import com.pojo.Entity.Equipment;
import com.pojo.Entity.EquipmentRental;
import com.pojo.mapper.EquipmentMapper;
import com.pojo.mapper.EquipmentRentalMapper;
import com.pojo.util.Tool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class EquipmentServiceImpl implements IEquipmentService {

    @Autowired
    EquipmentMapper equipmentMapper;
    @Autowired
    EquipmentRentalMapper equipmentRentalMapper;
    @Autowired
    RedisTemplate redisTemplate;
    private static final String BY_SUM_KEY="By_Sum_Key";
    private static final String BY_SUM_KEY_LOCK="By_Sum_Key_Lock";
    @Override
    public Integer insert(Equipment equipment) {
        equipment.setEInventory(equipment.getESum());
        return equipmentMapper.insert(equipment);
    }

    @Override
    public Integer modifyQuantity(Integer eID, Integer eInventory,String sPretime,String sPreEndtime, HttpServletRequest httpServletRequest) {
        Integer count=0;
        boolean check=false;
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date vPretime=null;
        Date vPreEndtime=null;
        if (sPretime!=null){
            if(sPretime.compareTo(sPreEndtime)>=0)
                return 0;
            String today= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
            if(today.compareTo(sPretime)>=0)
                return 0;
            try {
                vPretime=ft.parse(sPretime);
                vPreEndtime=ft.parse(sPreEndtime);
            }catch (Exception e){
                return null;
            }

        }
        System.out.println(vPretime);
        Integer uID= (Integer) redisTemplate.opsForHash().get(httpServletRequest.getHeader("identifying"),"uID");
        String key = BY_SUM_KEY+String.valueOf(uID) + ":" + String.valueOf(eID);
        String lock=BY_SUM_KEY_LOCK+String.valueOf(uID) + ":" + String.valueOf(eID);
        String uuid= String.valueOf(UUID.randomUUID());
        try {
            Integer sum=(Integer) redisTemplate.opsForValue().get(key);
             check= Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lock,uuid,300, TimeUnit.MILLISECONDS));
            if (check==false)
                return 0;
            if(sum==null)
                sum=0;
            if(Math.abs(sum+eInventory)>10){
                return 0;
            }
            redisTemplate.opsForValue().set(key,sum+eInventory);
            count= equipmentMapper.modifyQuantity(eID,eInventory);
            if(count!=null&&count>0){
                EquipmentRental equipmentRental=null;
                if(vPretime!=null){
                    Integer cost= Tool.getMoney(vPretime,vPreEndtime,equipmentMapper.findByeID(eID).getECost());
                    equipmentRental= new EquipmentRental(null,eInventory,eID,uID,vPretime,null,null,vPreEndtime,cost,0,0);
                }else{
                    equipmentRental= new EquipmentRental(null,eInventory,eID,uID,null,new Date(),null,null,0,0,0);
                }
                equipmentRentalMapper.insert(equipmentRental);
            }
            return count;
        }catch (Exception e){
            throw new ServiceException();
        }finally{
            unlock(lock,uuid);
        }
    }

    @Override
    public Integer update(Equipment equipment) {
        Equipment equipment1=equipmentMapper.findByeID(equipment.getEID());
        Integer count=equipment1.getESum()-equipment.getESum();
        if(equipment1.getEInventory()<count)
            return null;
        equipment.setEInventory(equipment1.getEInventory()-count);
        return equipmentMapper.update(equipment);
    }

    @Override
    public Equipment getEquipment(Integer eID) {
        return equipmentMapper.findByeID(eID);
    }

    @Override
    public List<Equipment> getlEquipment(Integer page, Integer number,String eType) {
        page=(page-1)*number;
        return equipmentMapper.findByPN(page,number,eType);
    }

    @Override
    public List<EquipmentRental> getlEquipmentRental(Integer page, Integer number, Integer erTYpe, Integer erReturn, Integer rID,HttpServletRequest httpServletRequest) {
        if(page!=null){
            page=(page-1)*number;
        }
        if(rID!=null)
            rID= (Integer) redisTemplate.opsForHash().get(httpServletRequest.getHeader("identifying"),"uID");
        return equipmentRentalMapper.findByPn(page,number,erTYpe,erReturn,rID);
    }

    @Override
    public Integer updateER(Integer erID, Integer erType, Integer erReturn) {
        EquipmentRental equipmentRental=equipmentRentalMapper.findByerID(erID);
        String key = BY_SUM_KEY+String.valueOf(equipmentRental.getRID()) + ":" + String.valueOf(equipmentRental.getEID());
        if(erType!=null){
            if(equipmentRental.getErTYpe()!=0)
                return 0;
            if(equipmentRental.getErBegintime()!=null&&erType==1){
                Integer cost= Tool.getMoney(equipmentRental.getErBegintime(),new Date(),equipmentMapper.findByeID(equipmentRental.getEID()).getECost());
                equipmentRental.setErEndtime(new Date());
                equipmentRental.setErCost(cost);
            }
            if(erType==2){
                Integer sum=(Integer) redisTemplate.opsForValue().get(key);
                redisTemplate.opsForValue().set(key,sum-equipmentRental.getErnumber());
                equipmentMapper.modifyQuantity(equipmentRental.getEID(),-equipmentRental.getErnumber());
            }
            equipmentRental.setErTYpe(erType);
        }
        if(erReturn!=null)
        {
            if(equipmentRental.getErReturn()!=0)
                return 0;
            if(equipmentRental.getErTYpe()!=1)
                return 0;
            if(erReturn==1){
                Integer sum=(Integer) redisTemplate.opsForValue().get(key);
                redisTemplate.opsForValue().set(key,sum-equipmentRental.getErnumber());
                equipmentMapper.modifyQuantity(equipmentRental.getEID(),-equipmentRental.getErnumber());
            }
            if(erReturn==2){
                Integer sum=(Integer) redisTemplate.opsForValue().get(key);
                redisTemplate.opsForValue().set(key,sum-equipmentRental.getErnumber());
                Equipment equipment=equipmentMapper.findByeID(equipmentRental.getEID());
                equipment.setESum(equipment.getESum()-equipmentRental.getErnumber());
                equipmentMapper.update(equipment);
            }
            equipmentRental.setErReturn(erReturn);
        }

        return equipmentRentalMapper.update(equipmentRental);
    }

    @Override
    public Integer getsum(String eType) {
        return equipmentMapper.getsum(eType);
    }

    @Override
    public Integer getsume(Integer erTYpe, Integer erReturn, Integer rID) {
        return equipmentRentalMapper.getsum(erTYpe,erReturn,rID);
    }

    @Override
    public Integer delete(Integer eID) {
            return equipmentMapper.delete(eID);
    }

    public void unlock(String key,String value){
        if (value.equals(redisTemplate.opsForValue().get(key)))
        redisTemplate.delete(key);
    };

}
